package com.lhkj.ct.meta.modules.questionnaire.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Maps;
import com.lhkj.ct.base.model.dto.PageQuery;
import com.lhkj.ct.base.mybatis.core.metadata.SqlOrder;
import com.lhkj.ct.base.mybatis.extension.service.impl.BatchHandleServiceImpl;
import com.lhkj.ct.base.utils.ShiroUtil;
import com.lhkj.ct.base.utils.Validate;
import com.lhkj.ct.meta.modules.gauge.common.enums.GaugeType;
import com.lhkj.ct.meta.modules.gauge.mapper.GaugeQuestionMapper;
import com.lhkj.ct.meta.modules.gauge.mapper.QnrMapper;
import com.lhkj.ct.meta.modules.gauge.model.entity.TblQnr;
import com.lhkj.ct.meta.modules.patient.mapper.PatientMapper;
import com.lhkj.ct.meta.modules.psychology.model.dto.GaugeAllotDto;
import com.lhkj.ct.meta.modules.psychology.model.vo.ViewAnswerVo;
import com.lhkj.ct.meta.modules.questionnaire.model.entity.TblQnrResult;
import com.lhkj.ct.meta.modules.questionnaire.mapper.QnrAllotRecordMapper;
import com.lhkj.ct.meta.modules.questionnaire.mapper.QnrResultMapper;
import com.lhkj.ct.meta.modules.questionnaire.model.entity.TblQnrAllotRecord;
import com.lhkj.ct.meta.modules.questionnaire.model.vo.QnrStatisticsVo;
import com.lhkj.ct.meta.modules.questionnaire.service.QnrAllotRecordService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 问卷分配记录 服务实现类
 * </p>
 *
 * @author jobob
 * @since 2023-10-26
 */
@Service
public class QnrAllotRecordServiceImpl extends BatchHandleServiceImpl<QnrAllotRecordMapper, TblQnrAllotRecord> implements QnrAllotRecordService {

    @Resource
    private PatientMapper patientMapper;
    @Resource
    private QnrResultMapper resultMapper;

    @Resource
    private GaugeQuestionMapper questionMapper;

    @Resource
    private QnrMapper qnrMapper;

    /**
     * 问卷分配
     */
    @Override
    public boolean allot(GaugeAllotDto allotDto) {
        // 分配的量表
        final Set<String> scaleIds = allotDto.getScaleIds();
        // 分配人
        final String createBy = ShiroUtil.getAuthUserInfo().getUserId();
        // 分配时间
        final LocalDateTime createTime = LocalDateTime.now();
        // 初始化档案id
        Set<String> patIds = new HashSet<>(allotDto.getPatIds());
        // 按标签
        if (CollectionUtil.isNotEmpty(allotDto.getPatLabelIds())) {
            patIds.addAll(patientMapper.selectUsersByLabels(allotDto.getPatLabelIds()));
        }
        // 按团体
        if (CollectionUtil.isNotEmpty(allotDto.getUnitIds())) {
            patIds.addAll(patientMapper.selectUsersByUnits(allotDto.getUnitIds()));
        }
        List<TblQnrAllotRecord> records = patIds.stream()
                .map(p -> scaleIds.stream()
                        .map(s ->
                                TblQnrAllotRecord
                                        .builder()
                                        .patId(p)
                                        .qnrId(s)
                                        .anonymous(false)
                                        .status(0)
                                        .createBy(createBy)
                                        .createTime(createTime)
                                        .build()
                        ).collect(Collectors.toList()))
                .flatMap(Collection::stream)
                .collect(Collectors.toList());
        return super.saveBatch(records);
    }

    /**
     * 问卷分配记录
     */
    @Override
    public IPage<TblQnrAllotRecord> selectAllotPage(TblQnrAllotRecord record, PageQuery pageQuery) {
        return getBaseMapper().selectAllotPage(generatePage(pageQuery, SqlOrder.desc(TblQnrAllotRecord::getCreateTime)),
                record,
                pageQuery);
    }

    /**
     * 根据分配记录查询问卷信息，题目，和作答进度
     *
     * @param allotId      分配记录
     * @param validateSelf 是否校验本人作答
     */
    @Override
    public Map<String, Object> selectQnrWithQuestionsByAllotId(String allotId, boolean validateSelf) {
        TblQnrAllotRecord record = getBaseMapper().selectRecordWithRid(allotId);
        Validate.isFalse(null == record, "记录已撤销，无法作答");
        Validate.isFalse(1 == record.getStatus(), "问卷已提交，不可再次作答");
        if (null == record.getRId()) {
            TblQnrResult qnrResult = new TblQnrResult();
            qnrResult.setAllotId(allotId);
            qnrResult.setQnrId(record.getQnrId());
            qnrResult.setPatId(record.getPatId());
            qnrResult.setPatName(record.getPatName());
            qnrResult.setPatSex(record.getPatSex());
            qnrResult.setPatAge(record.getPatAge());
            qnrResult.setStatus(0);
            resultMapper.insert(qnrResult);
            record.setRId(qnrResult.getId());
        }
        TblQnr qnr = qnrMapper.selectOne(new LambdaQueryWrapper<TblQnr>()
                .select(TblQnr::getId, TblQnr::getQnrName, TblQnr::getQuestionJson, TblQnr::getInstruction)
                .eq(TblQnr::getId, record.getQnrId()));
        // 判断问卷是否存在
        Validate.isFalse(null == qnr, "问卷已删除，无法继续作答");
        Map<String, Object> resMap = Maps.newHashMap();
        resMap.put("rId", record.getRId());
        resMap.put("info", qnr);
        resMap.put("questions", questionMapper.selectQutWithOptWithLogicByGaugeId(record.getQnrId(), GaugeType.QUESTIONNAIRE));
        resMap.put("answerJson", record.getAnswerJson());
        resMap.put("costTime", record.getCostTime());
        resMap.put("anonymous", record.getAnonymous());
        return resMap;
    }

    /**
     * 问卷统计
     */
    @Override
    public IPage<QnrStatisticsVo> statistics(PageQuery pageQuery) {
        return getBaseMapper().statistics(generatePage(pageQuery), pageQuery.getKeywords());
    }

    @Override
    public ViewAnswerVo viewAnswer(String allotId) {
        final ViewAnswerVo answerVo = getBaseMapper().viewAnswer(allotId);
        // 判断记录是否撤销
        Validate.isFalse(answerVo == null || answerVo.getReportStatus() != 1, "未作答完成,无法查看！");
        return answerVo;
    }
}
